//
//  KLAudioTool.m
//  HealthManage
//
//  Created by 陈华 on 2017/4/9.
//  Copyright © 2017年 kinglian. All rights reserved.
//

#import "KLAudioTool.h"
//#import "HRAudioPath.h"

@interface KLAudioTool () <AVAudioRecorderDelegate>
/**音频会话*/
@property(nonatomic,strong) AVAudioSession *audioSession;
/**录音类*/
@property(nonatomic,strong) AVAudioRecorder *audioRecorder;
/**录音设置*/
@property(nonatomic,strong) NSDictionary *recordSetting;

#pragma mark - 记录属性
/**计时器*/
@property(nonatomic,weak) NSTimer *timer;
/**音量回调block*/
@property(nonatomic,copy) VoiceMeters voiceMeters;

/**录音文件存储路径*/
@property(nonatomic,copy) NSString *voicePath;
/**录音开始时间戳*/
@property(nonatomic,assign) NSTimeInterval recordStartTime;
/**录音结束时间戳*/
@property(nonatomic,assign) NSTimeInterval recordEndTime;

@end

@implementation KLAudioTool


#pragma mark - 单例
static id _instance;
+ (instancetype)shareInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instance = [[self alloc]init];
    });
    return _instance;
}

- (instancetype)init
{
    if (self = [super init]) {
        
        //初始化录音设置
        NSMutableDictionary *setting = [NSMutableDictionary dictionary];
        setting[AVFormatIDKey] = @(kAudioFormatLinearPCM);
        setting[AVSampleRateKey] = @44100;
        setting[AVNumberOfChannelsKey] = @1;
        setting[AVLinearPCMBitDepthKey] = @16;
        setting[AVLinearPCMIsBigEndianKey] = @0;
        setting[AVLinearPCMIsFloatKey] = @0;
        self.recordSetting = setting;
        
        
        //初始化录音会话
        if (!self.audioSession) {
            self.audioSession = [AVAudioSession sharedInstance];
            
            if ([self.audioSession respondsToSelector:@selector(requestRecordPermission:)]) {
                [self.audioSession performSelector:@selector(requestRecordPermission:) withObject:^(BOOL isTrue){
                    if (isTrue) {
                        
                    }else{
                        NSLog(@"app需要访问您的麦克风。");
                    }
                    
                }];
            }
            [self.audioSession setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
            [self.audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
            [self.audioSession setActive:YES error:nil];
        }
    }
    return self;
}


#pragma mark - API

/**是否有录音权限*/
- (BOOL)isAudioAvaiable
{
    __block BOOL open = NO;
    AVAudioSession *session = [AVAudioSession sharedInstance];
    if ([session respondsToSelector:@selector(requestRecordPermission:)]) {
        [session performSelector:@selector(requestRecordPermission:) withObject:^(BOOL status) {
            open = status;
        }];
    } else {
        open = YES;
    }
    
    return open;
}

/**开始录制*/
- (BOOL)startRecord:(VoiceMeters)voiceMeters
{
    if (self.audioRecorder.isRecording) {
        return NO;
    }
    //保存block
    self.voiceMeters = voiceMeters;
    
    //创建录音对象
//    self.voicePath = [HRAudioPath recordPathOrigin];
    self.voicePath = nil;
    NSURL *url = [NSURL URLWithString:self.voicePath];
    self.audioRecorder = [[AVAudioRecorder alloc]initWithURL:url settings:self.recordSetting error:nil];
    
    //监听音量大小
    self.audioRecorder.meteringEnabled = YES;
    
    //准备录音
    BOOL success = [self.audioRecorder prepareToRecord];
    if (!success) {
        return NO;
    }
    
    //开始录音
    success = [self.audioRecorder record];
    self.recordStartTime = [[NSDate new] timeIntervalSince1970];
    
    //添加计时器，监听音量
    NSTimer *timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(timeChange) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    self.timer = timer;
    
    //返回
    return success;
}

/**结束录制*/
- (void)endRecord
{
    if (self.audioRecorder) {
        [self.audioRecorder stop];
        self.recordEndTime = [[NSDate new] timeIntervalSince1970];
        [self.timer invalidate];
        self.voiceMeters = nil;
        

        NSURL *url = [NSURL URLWithString:self.voicePath];
        
        
        NSDictionary *optional =@{AVURLAssetPreferPreciseDurationAndTimingKey:@(YES)};
        
        AVURLAsset *urlAsset = [[AVURLAsset alloc]initWithURL:url options:optional];

        
        CMTime time = urlAsset.duration;
        NSLog(@"%f",time.value);
        CGFloat dur = urlAsset.duration.value / urlAsset.duration.timescale;
        
        NSLog(@"time = %f", dur);
        NSLog(@"timeP = %f", (self.recordEndTime - self.recordStartTime));
        
    }
    
}



#pragma mark - 事件监听
/**计时器改变*/
- (void)timeChange
{
    //更新音量
    [self.audioRecorder updateMeters];


    //计算音量
    [self calculatorMeters];
    
}


#pragma mark - AVAudioRecorderDelegate



#pragma mark - 工具方法
/**计算音量方法1*/
-(void)calculatorMeters
{
    //计算音量 lg(100) = 20db  -- 根据分贝值计算当前线性值
    CGFloat lowPassResults = pow(10, (0.05 * [self.audioRecorder peakPowerForChannel:0]));
    
    //计算音量
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.voiceMeters) {
            self.voiceMeters(lowPassResults);
        }
    });
}

/**计算音量方法2*/
- (void)calculatorMeters2
{
    float   level;                // The linear 0.0 .. 1.0 value we need.
    float   minDecibels = -80.0f; // Or use -60dB, which I measured in a silent room.
    float   decibels    = [self.audioRecorder averagePowerForChannel:0];
    
    if (decibels < minDecibels)
    {
        level = 0.0f;
    }
    else if (decibels >= 0.0f)
    {
        level = 1.0f;
    }
    else
    {
        float   root            = 2.0f;
        float   minAmp          = powf(10.0f, 0.05f * minDecibels);
        float   inverseAmpRange = 1.0f / (1.0f - minAmp);
        float   amp             = powf(10.0f, 0.05f * decibels);
        float   adjAmp          = (amp - minAmp) * inverseAmpRange;
        
        level = powf(adjAmp, 1.0f / root);
    }
    
    /* level 范围[0 ~ 1], 转为[0 ~120] 之间 */
    dispatch_async(dispatch_get_main_queue(), ^{
        //CGFloat voice = level * 120;
        if (self.voiceMeters) {
//            self.voiceMeters(voice/10.0);
            self.voiceMeters(level);
        }
    });
}

@end


























